#include "bsp_us015_icu_io.h"
#include "stm32f4xx_ll_tim.h"

typedef struct  
{
  TIM_TypeDef *TIMx;
  uint32_t Channel;
  uint32_t SR_CCxIF_Mask;
  uint32_t DIER_CCxIE_Mask;
  uint32_t ICFilter;
  uint32_t* CCRx;
  

}BSP_US015_ICU_Config_Type;

typedef struct
{
  uint32_t u4State;
  uint32_t u4RisingTM;/*Unit is tick*/
  uint32_t u4FallingTM;/*Unit is tick*/
  uint32_t u4PulseWidth;/*Unit is tick*/
}BSP_US015_ICU_State_Type;

static const BSP_US015_ICU_Config_Type cstBSP_US015_ICU_Config[MAX_ICU_CHANNEL]={
  {
    .TIMx = TIM2,
    .Channel=LL_TIM_CHANNEL_CH2,
    .SR_CCxIF_Mask=TIM_SR_CC2IF,
    .DIER_CCxIE_Mask=TIM_DIER_CC2IE,
    .ICFilter=LL_TIM_IC_FILTER_FDIV32_N8,
    .CCRx = &TIM2->CCR2,
  },
  {
    .TIMx = TIM2,
    .Channel=LL_TIM_CHANNEL_CH3,
    .SR_CCxIF_Mask=TIM_SR_CC3IF,
    .DIER_CCxIE_Mask=TIM_DIER_CC3IE,
    .ICFilter=LL_TIM_IC_FILTER_FDIV32_N8,
    .CCRx = &TIM2->CCR3,
  },
};

static BSP_US015_ICU_State_Type stBSP_US015_ICU_State[MAX_ICU_CHANNEL];

void bsp_us015_icu_io_init(void)
{
  int32_t i;
  const BSP_US015_ICU_Config_Type *pcst_Config;

  for(i=0;i<MAX_ICU_CHANNEL;i++){
    stBSP_US015_ICU_State[i].u4State = 0;
    stBSP_US015_ICU_State[i].u4RisingTM = 0;
    stBSP_US015_ICU_State[i].u4FallingTM = 0;
    stBSP_US015_ICU_State[i].u4PulseWidth = 0;

    pcst_Config = &cstBSP_US015_ICU_Config[i];
    
    /*Config as Input capture*/
    LL_TIM_IC_SetActiveInput(pcst_Config->TIMx, pcst_Config->Channel, LL_TIM_ACTIVEINPUT_DIRECTTI);

    /*Init to capture rising edge*/
    LL_TIM_IC_SetFilter(pcst_Config->TIMx, pcst_Config->Channel, LL_TIM_IC_FILTER_FDIV32_N8);
    LL_TIM_IC_SetPolarity(pcst_Config->TIMx, pcst_Config->Channel, LL_TIM_IC_POLARITY_RISING);

    /*Config channel to capture*/
    /*Ref to LL_TIM_EnableIT_CC2*/
    SET_BIT(pcst_Config->TIMx->DIER, pcst_Config->DIER_CCxIE_Mask);
    LL_TIM_CC_EnableChannel(pcst_Config->TIMx, pcst_Config->Channel);

    /*Timer's clock /bus init is placed at MX_TIM2_Init*/
    /*LL_TIM_EnableCounter(pcst_Config->TIMx);*/
  }
  
}

void bsp_us015_icu_io_interrupt(uint32_t u4ChannelID)
{
  const BSP_US015_ICU_Config_Type *pcst_Config;
  BSP_US015_ICU_State_Type *pst_State;
  uint32_t flag;
  uint32_t tmpTM;

  pcst_Config = &cstBSP_US015_ICU_Config[u4ChannelID];
  pst_State = &stBSP_US015_ICU_State[u4ChannelID];

  /* Ref to LL_TIM_IC_GetCaptureCH2 */
  flag = ((READ_BIT(pcst_Config->TIMx->SR, pcst_Config->SR_CCxIF_Mask) == (pcst_Config->SR_CCxIF_Mask)) ? 1UL : 0UL);

  if(flag){
    /* Ref to LL_TIM_ClearFlag_CC2 */
    WRITE_REG(pcst_Config->TIMx->SR, ~(pcst_Config->SR_CCxIF_Mask));

    /*Ref to LL_TIM_IC_GetCaptureCH2*/
    tmpTM = (uint32_t)(*(pcst_Config->CCRx));

    if(pst_State->u4State == 0){
      /*Rising got, start capture falling*/
      pst_State->u4RisingTM = tmpTM;
      pst_State->u4State = 1;

      LL_TIM_IC_SetFilter(pcst_Config->TIMx, pcst_Config->Channel, LL_TIM_IC_FILTER_FDIV1);
      LL_TIM_IC_SetPolarity(pcst_Config->TIMx, pcst_Config->Channel, LL_TIM_IC_POLARITY_FALLING);
    }
    else if(pst_State->u4State == 1){
      /*Falling got, start capture rising(next cycle)*/
      pst_State->u4FallingTM = tmpTM;
      LL_TIM_IC_SetFilter(pcst_Config->TIMx, pcst_Config->Channel, LL_TIM_IC_FILTER_FDIV32_N8);
      LL_TIM_IC_SetPolarity(pcst_Config->TIMx, pcst_Config->Channel, LL_TIM_IC_POLARITY_RISING);

      pst_State->u4State = 0;

      if(pst_State->u4FallingTM > pst_State->u4RisingTM){
        pst_State->u4PulseWidth = pst_State->u4FallingTM - pst_State->u4RisingTM;
      }

    }
    else{
      /*do nothing*/
    }
  }
}

uint32_t bsp_us015_icu_io_get_pulseWidth(uint32_t u4ChannelID)
{
  /*Unit is tick,according to TimerxCHy config to figure out the LSB*/
  return stBSP_US015_ICU_State[u4ChannelID].u4PulseWidth;
}